#include "napi/native_api.h"
#include "rawfile/raw_file_manager.h"
#include "rawfile/raw_file.h"
//#include <multimedia/image_framework/image_pixel_map_mdk.h>
#include <multimedia/image_framework/image_source_mdk.h>

#include <hilog/log.h>
#include <string>


const int GLOBAL_RESMGR = 0xFF00;
const char *TAG = "[madixin]";

// 用户提供的上下文数据，在原生方法（初始化数据）、executeCB、completeCB之间传递数据
struct ImageRequestData {
    napi_async_work asyncWork = nullptr;
    napi_deferred deferred = nullptr;
    NativeResourceManager *mNativeResMgr = nullptr;
    std::string src = "";
    napi_value result;
};

// 业务逻辑处理函数，由worker线程池调度执行。
static void getImageInWorker(napi_env env, void *data) {
    ImageRequestData *imageRequestData = (ImageRequestData *)data;

    RawFile *rawFile = OH_ResourceManager_OpenRawFile(imageRequestData->mNativeResMgr, imageRequestData->src.c_str());
    if (rawFile != NULL) {
        long len = OH_ResourceManager_GetRawFileSize(rawFile);
        // std::unique_ptr<uint8_t[]> data = std::make_unique<uint8_t[]>(len);
        uint8_t *data = static_cast<uint8_t *>(malloc(len));

        int res = OH_ResourceManager_ReadRawFile(rawFile, data, len);

        OH_LOG_Print(LOG_APP, LOG_INFO, GLOBAL_RESMGR, TAG, "raw filezie = %{public}ld", len);

        OH_LOG_Print(LOG_APP, LOG_INFO, GLOBAL_RESMGR, TAG, "333 filezie = %{public}d", res);

        OhosImageSource src;
        src.buffer = data;
        src.bufferSize = len;

        OhosImageSourceOps ops{};
        //        ops.density = 1;
        //        ops.pixelFormat = 4;

        OhosImageSize size{};
        //        size.width = 1920;
        //        size.height = 1280;
        //   ops.size = size;

        napi_value imageSource;
        napi_value pixelmap;

        int32_t ret = OH_ImageSource_Create(env, &src, &ops, &imageSource);
        OH_LOG_Print(LOG_APP, LOG_INFO, GLOBAL_RESMGR, TAG, "OH_ImageSource_Create res = %{public}d", ret);

        const ImageSourceNative *pImageSourceNative = OH_ImageSource_InitNative(env, imageSource);
        OhosImageDecodingOps ohosImageDecodingOps{};
        ohosImageDecodingOps.editable = 0;
        ohosImageDecodingOps.fitDensity = 220;
        // ohosImageDecodingOps.size = size;
        OH_ImageSource_CreatePixelMap(pImageSourceNative, &ohosImageDecodingOps, &pixelmap);
        OH_LOG_Print(LOG_APP, LOG_INFO, GLOBAL_RESMGR, TAG, "OH_ImageSource_CreatePixelMap res = %{public}d", ret);
        

        OH_ResourceManager_CloseRawFile(rawFile);

        OH_ResourceManager_ReleaseNativeResourceManager(imageRequestData->mNativeResMgr);

        OH_LOG_Print(LOG_APP, LOG_INFO, GLOBAL_RESMGR, TAG, "sss src = ppppppppppppp");
        imageRequestData->result = pixelmap;
    }
    else{
        OH_LOG_Print(LOG_APP, LOG_INFO, GLOBAL_RESMGR, TAG, "file is null");
    }
}

// 获取图片后的回调函数
static void getImagePromiseCompleteCB(napi_env env, napi_status status, void *data) {
    OH_LOG_Print(LOG_APP, LOG_INFO, GLOBAL_RESMGR, TAG, "sss src = eeeeeeeeeeeeee");
    ImageRequestData *imageRequestData = (ImageRequestData *)data;
    napi_value result = nullptr;
  //  napi_create_string_utf8(env, imageRequestData->result.c_str(), 3, &result);
    napi_resolve_deferred(env, imageRequestData->deferred, imageRequestData->result);

    //    // 删除napi_ref对象
    //    if (getPixelMapData->callback != nullptr) {
    //        napi_delete_reference(env, addonData->callback);
    //    }

    // 删除异步工作项
    napi_delete_async_work(env, imageRequestData->asyncWork);
    delete imageRequestData;
    imageRequestData = nullptr;
}


static napi_value getPixelMap(napi_env env, napi_callback_info info) {
    size_t argc = 2;
    napi_value args[2] = {nullptr};

    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
    NativeResourceManager *mNativeResMgr = OH_ResourceManager_InitNativeResourceManager(env, args[0]);

    size_t strSize;
    char srcBuf[2048];
    napi_get_value_string_utf8(env, args[1], srcBuf, sizeof(srcBuf), &strSize);
    std::string src(srcBuf, strSize);

    // 创建promise
    napi_value promise = nullptr;
    napi_deferred deferred = nullptr;
    napi_create_promise(env, &deferred, &promise);

    auto imageRequestData = new ImageRequestData{
        .asyncWork = nullptr,
    };
    imageRequestData->deferred = deferred;
    imageRequestData->src = src;
    imageRequestData->mNativeResMgr = mNativeResMgr;

    OH_LOG_Print(LOG_APP, LOG_INFO, GLOBAL_RESMGR, TAG, "sss src = 11111111111111111");

    // 创建async work，创建成功后通过最后一个参数(addonData->asyncWork)返回async work的handle
    napi_value resourceName = nullptr;
    napi_create_string_utf8(env, "addAsyncCallback", NAPI_AUTO_LENGTH, &resourceName);
    napi_create_async_work(env, nullptr, resourceName, getImageInWorker, getImagePromiseCompleteCB,
                           (void *)imageRequestData, &imageRequestData->asyncWork);
    // 将刚创建的async work加到队列，由底层去调度执行
    napi_queue_async_work(env, imageRequestData->asyncWork);

    OH_LOG_Print(LOG_APP, LOG_INFO, GLOBAL_RESMGR, TAG, "sss src = 2222222222222222");

    return promise;
}


static napi_value getSyncPixelMap(napi_env env, napi_callback_info info) {
    size_t argc = 2;
    napi_value args[2] = {nullptr};

    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);

    napi_valuetype srcType;
    napi_typeof(env, args[0], &srcType);

    NativeResourceManager *mNativeResMgr = OH_ResourceManager_InitNativeResourceManager(env, args[0]);

    size_t strSize;
    char srcBuf[2048];
    napi_get_value_string_utf8(env, args[1], srcBuf, sizeof(srcBuf), &strSize);
    std::string src(srcBuf, strSize);
    // std::string dirName(srcBuf, strSize);


    OH_LOG_Print(LOG_APP, LOG_INFO, GLOBAL_RESMGR, TAG, "sss src = %{public}s", srcBuf);
    OH_LOG_Print(LOG_APP, LOG_INFO, GLOBAL_RESMGR, TAG, "sss srctype = %{public}d", srcType);


    RawFile *rawFile = OH_ResourceManager_OpenRawFile(mNativeResMgr, srcBuf);
    if (rawFile != NULL) {
        long len = OH_ResourceManager_GetRawFileSize(rawFile);
        // std::unique_ptr<uint8_t[]> data = std::make_unique<uint8_t[]>(len);
        uint8_t *data = static_cast<uint8_t *>(malloc(len));

        int res = OH_ResourceManager_ReadRawFile(rawFile, data, len);

        OH_LOG_Print(LOG_APP, LOG_INFO, GLOBAL_RESMGR, TAG, "raw filezie = %{public}ld", len);

        OH_LOG_Print(LOG_APP, LOG_INFO, GLOBAL_RESMGR, TAG, "333 filezie = %{public}d", res);

        OhosImageSource src;
        src.buffer = data;
        src.bufferSize = len;

        OhosImageSourceOps ops{};
//        ops.density = 1;
//        ops.pixelFormat = 4;

        OhosImageSize size{};
//        size.width = 1920;
//        size.height = 1280;
     //   ops.size = size;

        napi_value imageSource;
        napi_value pixelmap;

        int32_t ret = OH_ImageSource_Create(env, &src, &ops, &imageSource);
        OH_LOG_Print(LOG_APP, LOG_INFO, GLOBAL_RESMGR, TAG, "OH_ImageSource_Create res = %{public}d", ret);

        const ImageSourceNative *pImageSourceNative = OH_ImageSource_InitNative(env, imageSource);
        OhosImageDecodingOps ohosImageDecodingOps{};
        ohosImageDecodingOps.editable=0;
        ohosImageDecodingOps.fitDensity=220;
       // ohosImageDecodingOps.size = size;
        OH_ImageSource_CreatePixelMap(pImageSourceNative, &ohosImageDecodingOps, &pixelmap);
        OH_LOG_Print(LOG_APP, LOG_INFO, GLOBAL_RESMGR, TAG, "OH_ImageSource_CreatePixelMap res = %{public}d", ret);
        
        OH_ResourceManager_CloseRawFile(rawFile);

        OH_ResourceManager_ReleaseNativeResourceManager(mNativeResMgr);

        return pixelmap;

    } else {
        OH_LOG_Print(LOG_APP, LOG_INFO, GLOBAL_RESMGR, TAG, "no raw file");
    }
    
    return nullptr;
}


EXTERN_C_START
static napi_value Init(napi_env env, napi_value exports) {
    napi_property_descriptor desc[] = {
        {"getPixelMap", nullptr, getPixelMap, nullptr, nullptr, nullptr, napi_default, nullptr},
        {"getSyncPixelMap", nullptr, getSyncPixelMap, nullptr, nullptr, nullptr, napi_default, nullptr}};
    napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
    return exports;
}
EXTERN_C_END

static napi_module demoModule = {
    .nm_version = 1,
    .nm_flags = 0,
    .nm_filename = nullptr,
    .nm_register_func = Init,
    .nm_modname = "entry",
    .nm_priv = ((void *)0),
    .reserved = {0},
};

extern "C" __attribute__((constructor)) void RegisterEntryModule(void) { napi_module_register(&demoModule); }
